/*
 * Copyright 2017 yangchong211（github.com/yangchong211）
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.yc.kernel.impl.media;

import ohos.agp.graphics.Surface;
import ohos.agp.graphics.SurfaceOps;
import ohos.app.Context;
import ohos.app.dispatcher.task.TaskPriority;
import ohos.global.resource.RawFileDescriptor;
import ohos.media.audio.AudioManager;
import ohos.media.common.Source;
import ohos.media.player.Player;

import com.yc.kernel.inter.AbstractVideoPlayer;
import com.yc.kernel.inter.VideoPlayerListener;
import com.yc.kernel.utils.PlayerConstant;

import java.util.Map;

/**
 * AudioFocusManager
 *
 * @since 2021-05-10
 */
public class OhosMediaPlayer extends AbstractVideoPlayer {
    private static final long TIME_RATE = 1000;
    protected Player mMediaPlayer;
    private int mBufferedPercent;
    private Context mAppContext;
    private boolean mIsPreparing;

    /**
     * OhosMediaPlayer
     *
     * @param context context
     */
    public OhosMediaPlayer(Context context) {
        mAppContext = context.getApplicationContext();
    }

    @Override
    public void initPlayer() {
        mMediaPlayer = new Player(mAppContext);
        setOptions();
        initListener();
    }

    /**
     * MediaPlayer视频播放器监听listener
     */
    private void initListener() {
        mMediaPlayer.setAudioStreamType(AudioManager.AudioVolumeType.STREAM_MUSIC.getValue());
        mMediaPlayer.setPlayerCallback(playerListener);
    }

    /**
     * 设置播放地址
     *
     * @param path 播放地址
     * @param headers 播放地址请求头
     */
    @Override
    public void setDataSource(String path, Map<String, String> headers) {
        // 设置dataSource
        if (path == null || path.length() == 0) {
            if (mPlayerEventListener != null) {
                mPlayerEventListener.onInfo(PlayerConstant.MEDIA_INFO_URL_NULL, 0);
            }
            return;
        }
        try {
            Source source = new Source(path, headers);
            mMediaPlayer.setSource(source);
        } catch (Exception e) {
            mPlayerEventListener.onError(PlayerConstant.ErrorType.TYPE_PARSE, e.getMessage());
        }
    }

    /**
     * 用于播放raw和asset里面的视频文件
     *
     * @param fd fd
     */
    @Override
    public void setDataSource(RawFileDescriptor fd) {
        mMediaPlayer.setSource(fd);
    }

    /**
     * 播放
     */
    @Override
    public void start() {
        if (mMediaPlayer.isNowPlaying()) {
            return;
        }
        try {
            mMediaPlayer.play();
        } catch (IllegalStateException e) {
            mPlayerEventListener.onError(PlayerConstant.ErrorType.TYPE_UNEXPECTED, e.getMessage());
        }
    }

    /**
     * 暂停
     */
    @Override
    public void pause() {
        try {
            mMediaPlayer.pause();
        } catch (IllegalStateException e) {
            mPlayerEventListener.onError(PlayerConstant.ErrorType.TYPE_UNEXPECTED, e.getMessage());
        }
    }

    /**
     * 停止
     */
    @Override
    public void stop() {
        try {
            mMediaPlayer.stop();
        } catch (IllegalStateException e) {
            mPlayerEventListener.onError(PlayerConstant.ErrorType.TYPE_UNEXPECTED, e.getMessage());
        }
    }

    @Override
    public void prepareAsync() {
        try {
            mAppContext.getGlobalTaskDispatcher(TaskPriority.DEFAULT).asyncDispatch(() -> {
                mIsPreparing = true;
                mMediaPlayer.prepare();
            });
        } catch (IllegalStateException e) {
            mPlayerEventListener.onError(PlayerConstant.ErrorType.TYPE_UNEXPECTED, e.getMessage());
        }
    }

    /**
     * 重置播放器
     */
    @Override
    public void reset() {
        mMediaPlayer.reset();
        mMediaPlayer.setVideoSurface(null);
        mMediaPlayer.setSurfaceOps(null);
        mMediaPlayer.setVolume(1);
    }

    /**
     * 是否正在播放
     *
     * @return return
     */
    @Override
    public boolean isPlaying() {
        return mMediaPlayer.isNowPlaying();
    }

    /**
     * 调整进度
     *
     * @param time time
     */
    @Override
    public void seekTo(long time) {
        try {
            mMediaPlayer.rewindTo(time * TIME_RATE);
        } catch (IllegalStateException e) {
            mPlayerEventListener.onError(PlayerConstant.ErrorType.TYPE_UNEXPECTED, e.getMessage());
        }
    }

    /**
     * 释放播放器
     */
    @Override
    public void release() {
        if (mMediaPlayer != null) {
            mMediaPlayer.release();
        }
    }

    /**
     * 获取当前播放的位置
     *
     * @return return
     */
    @Override
    public long getCurrentPosition() {
        return mMediaPlayer.getCurrentTime();
    }

    /**
     * 获取视频总时长
     *
     * @return return
     */
    @Override
    public long getDuration() {
        return mMediaPlayer.getDuration();
    }

    /**
     * 获取缓冲百分比
     *
     * @return 获取缓冲百分比
     */
    @Override
    public int getBufferedPercentage() {
        return mBufferedPercent;
    }

    /**
     * 设置渲染视频的View,主要用于TextureView
     *
     * @param surface surface
     */
    @Override
    public void setSurface(Surface surface) {
        if (surface != null) {
            try {
                mMediaPlayer.setVideoSurface(surface);
            } catch (Exception e) {
                mPlayerEventListener.onError(PlayerConstant.ErrorType.TYPE_UNEXPECTED, e.getMessage());
            }
        }
    }

    /**
     * 设置渲染视频的View,主要用于SurfaceView
     *
     * @param holder holder
     */
    @Override
    public void setDisplay(SurfaceOps holder) {
        try {
            mMediaPlayer.setSurfaceOps(holder);
        } catch (Exception e) {
            mPlayerEventListener.onError(PlayerConstant.ErrorType.TYPE_UNEXPECTED, e.getMessage());
        }
    }

    /**
     * 设置音量
     *
     * @param v1 v1
     * @param v2 v2
     */
    @Override
    public void setVolume(float v1, float v2) {
        try {
            mMediaPlayer.setVolume(v1);
        } catch (Exception e) {
            mPlayerEventListener.onError(PlayerConstant.ErrorType.TYPE_UNEXPECTED, e.getMessage());
        }
    }

    /**
     * 设置是否循环播放
     *
     * @param isLooping 布尔值
     */
    @Override
    public void setLooping(boolean isLooping) {
        try {
            mMediaPlayer.enableSingleLooping(isLooping);
        } catch (Exception e) {
            mPlayerEventListener.onError(PlayerConstant.ErrorType.TYPE_UNEXPECTED, e.getMessage());
        }
    }

    @Override
    public void setOptions() {
    }

    /**
     * 设置播放速度
     *
     * @param speed 速度
     */
    @Override
    public void setSpeed(float speed) {
        try {
            mMediaPlayer.setPlaybackSpeed(speed);
        } catch (Exception e) {
            mPlayerEventListener.onError(PlayerConstant.ErrorType.TYPE_UNEXPECTED, e.getMessage());
        }
    }

    /**
     * 获取播放速度
     *
     * @return 播放速度
     */
    @Override
    public float getSpeed() {
        try {
            return mMediaPlayer.getPlaybackSpeed();
        } catch (Exception e) {
            mPlayerEventListener.onError(PlayerConstant.ErrorType.TYPE_UNEXPECTED, e.getMessage());
        }
        return 1f;
    }

    /**
     * 获取当前缓冲的网速
     *
     * @return 获取网络
     */
    @Override
    public long getTcpSpeed() {
        // no support
        return 0;
    }

    Player.IPlayerCallback playerListener = new Player.IPlayerCallback() {
        @Override
        public void onPrepared() {
            mPlayerEventListener.onPrepared();
            start();
        }

        @Override
        public void onMessage(int what, int extra) {
            // 解决MEDIA_INFO_VIDEO_RENDERING_START多次回调问题
            if (what == PlayerConstant.MEDIA_INFO_VIDEO_RENDERING_START) {
                if (mIsPreparing) {
                    mPlayerEventListener.onInfo(what, extra);
                    mIsPreparing = false;
                }
            } else {
                mPlayerEventListener.onInfo(what, extra);
            }
        }

        @Override
        public void onError(int what, int extra) {
            mPlayerEventListener.onError(PlayerConstant.ErrorType.TYPE_UNEXPECTED, "监听异常" + what + ", extra: " + extra);
            release();
        }

        @Override
        public void onResolutionChanged(int width, int height) {
            int videoWidth = mMediaPlayer.getVideoWidth();
            int videoHeight = mMediaPlayer.getVideoHeight();
            if (videoWidth != 0 && videoHeight != 0) {
                mPlayerEventListener.onVideoSizeChanged(videoWidth, videoHeight);
            }
        }

        @Override
        public void onPlayBackComplete() {
            mPlayerEventListener.onCompletion();
        }

        @Override
        public void onRewindToComplete() {
        }

        @Override
        public void onBufferingChange(int percent) {
            mBufferedPercent = percent;
        }

        @Override
        public void onNewTimedMetaData(Player.MediaTimedMetaData mediaTimedMetaData) {
        }

        @Override
        public void onMediaTimeIncontinuity(Player.MediaTimeInfo mediaTimeInfo) {
        }
    };

    @Override
    public void setPlayerEventListener(VideoPlayerListener playerEventListener) {
        super.setPlayerEventListener(playerEventListener);
    }
}
